package pers.qianyu.module.security.util;

import cn.hutool.core.util.StrUtil;
import pers.qianyu.module.core.constants.TokenConstants;
import pers.qianyu.module.core.domain.system.entity.SysResourcePO;
import pers.qianyu.module.core.domain.system.vo.SysResourceVO;
import pers.qianyu.module.security.domain.LoginUser;
import pers.qianyu.module.security.exception.PreAuthorizeException;
import pers.qianyu.module.security.exception.SecurityErrorCodeEnum;
import pers.qianyu.module.security.model.RequestInfoModel;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * @author mizzle rain
 * @date 2021-05-03 21:06
 */
public class SecurityUtil {
    public static final Set<SysResourcePO> ACL = new HashSet<>();

    /**
     * 检查当前请求是否在访问控制名单里面
     */
    public static boolean inACL(RequestInfoModel model) {
        String uri = model.getUri();
        for (SysResourcePO sysResourcePO : ACL) {
            if (isMatch(sysResourcePO.getUri(), uri) &&
                    Objects.equals(model.getMethod(), sysResourcePO.getMethod())) {
                return true;
            }
        }
        return false;
    }

    public static LoginUser getLoginUser(HttpServletRequest req) {
        LoginUser loginUser = new LoginUser();
        String token = req.getHeader(TokenConstants.HEADER);
        loginUser.setToken(token);
        loginUser.setLoginTime(System.currentTimeMillis());
        loginUser.setIpAddr(Objects.nonNull(req.getHeader("X-Real-IP"))
                ? req.getHeader("X-Real-IP") : req.getRemoteAddr());
        return loginUser;
    }

    public static void checkToken(HttpServletRequest req) {
        String token = req.getHeader(TokenConstants.HEADER);
        if (StrUtil.isBlank(token)) {
            throw new PreAuthorizeException(SecurityErrorCodeEnum.EMPTY_TOKEN);
        }
    }

    /**
     * 检查uri是否匹配
     *
     * @param src    数据库中的uri，可能带有*
     * @param target 请求uri
     * @return 是否匹配
     */
    public static boolean isMatch(String src, String target) {
        if (StrUtil.isBlank(src) || StrUtil.isBlank(target)) {
            return false;
        }
        if (target.startsWith("/")) {
            target = target.substring(1);
        }
        if (src.startsWith("/")) {
            src = src.substring(1);
        }
        String[] targetArr = target.split("/");
        String[] srcArr = src.split("/");
        if (targetArr.length != srcArr.length) {
            return false;
        }
        for (int i = 0; i < targetArr.length; i++) {
            if (!Objects.equals(targetArr[i], srcArr[i]) && !srcArr[i].equals("*")) {
                return false;
            }
        }
        return true;
    }

    /**
     * 检查资源列表中是否包含model中的资源
     */
    public static void checkContains(Set<SysResourceVO> resourceList, RequestInfoModel model) {
        String reqUri = model.getUri();
        String reqMethod = model.getMethod();
        for (SysResourceVO sysResourceVO : resourceList) {
            if (isMatch(sysResourceVO.getUri(), reqUri) &&
                    Objects.equals(sysResourceVO.getMethod(), reqMethod)) {
                return;
            }
        }
        throw new PreAuthorizeException(SecurityErrorCodeEnum.INVALID_PERMISSION);
    }
}
